<template>
  <div class="flex flex-row">
    <el-col :span="4">
      <div id="stencil"></div>
    </el-col>
    <!-- 1. x6 容器 -->
    <el-col :span="14">
      <div id="x6Container" ref="containerRef"></div>
    </el-col>

    <!--1、右侧工具栏 start-->
    <el-col :span="8" class="h-full">
      <el-form :model="formData">
        <el-form-item label="数据">
          <el-select v-model="formData.id" placeholder="请选择数据" @change="onIdChange">
            <el-option v-for="item in dropdownData.tableData" :key="item.id" :value="item.id">
              {{ item.title }}
            </el-option>
          </el-select>
        </el-form-item>

        <el-form-item label="内容" v-show="formData.content !== ''">
          <el-input v-model="formData.content" readOnly />
        </el-form-item>
      </el-form>
      <el-button type="primary" @click="toJson">toJSON</el-button>
    </el-col>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, reactive, UnwrapRef } from "vue";
import { Graph, Shape, Cell } from "@antv/x6";
import { Stencil } from "@antv/x6-plugin-stencil";

let graph: Graph | null = null;
let stencil: Stencil;
let curCel: Cell | null;

const tableData = [
  {
    id: 1,
    title: "标题1",
    content: "内容1"
  },
  {
    id: 2,
    title: "标题2",
    content: "内容2"
  },
  {
    id: 3,
    title: "标题3",
    content: "内容3"
  }
];
interface FormDataModel {
  id: any;
  title: any;
  content: any;
}

// 表单数据定义
const formData: UnwrapRef<FormDataModel> = reactive({
  id: "",
  title: "",
  content: ""
});

// 自定义节点
Graph.registerNode("custom-rect", {
  inherit: "rect", // 继承基础矩形
  width: 200,
  height: 60,
  markup: [
    {
      tagName: "rect", // 标签名称
      selector: "body" // 选择器
    },
    {
      tagName: "image",
      selector: "img"
    },
    {
      tagName: "text",
      selector: "label"
    },
    {
      tagName: "text",
      selector: "text"
    }
  ],
  attrs: {
    body: {
      stroke: "#8f8f8f",
      strokeWidth: 1,
      fill: "#fff",
      rx: 6,
      ry: 6
    },
    img: {
      "xlink:href": "https://gw.alipayobjects.com/zos/antfincdn/FLrTNDvlna/antv.png",
      width: 16,
      height: 16,
      x: 12,
      y: 12
    },
    label: {
      text: "Node",
      refX: 40,
      refY: 14,
      fill: "rgba(0,0,0,0.85)",
      fontSize: 12,
      "text-anchor": "start"
    },
    rect: {
      class: "markupTest05Rect",
      fill: "#fff",
      rx: 3,
      ry: 3,
      refWidth: 1,
      refHeight: 1,
      refX: 0,
      refY: 0
    },
    text: {
      text: "this is content text",
      refX: 40,
      refY: 38,
      fontSize: 12,
      fill: "rgba(0,0,0,0.6)",
      "text-anchor": "start"
    }
  }
});
// 1.初始化数据
const originalData = ref({
  // 节点
  nodes: [],
  // 边
  edges: []
});
// 2.初始化画布
const init = () => {
  // 初始化 x6 图背景板
  // 创建一个新的 Graph 实例
  graph = new Graph({
    // 指定 Graph 的容器元素
    container: document.getElementById("x6Container")!,

    // 自动调整 Graph 的大小以适应容器
    autoResize: true,

    // 设置背景颜色
    background: {
      color: "#fffbe6" // 设置画布背景颜色
    },
    // 网格设置
    grid: {
      visible: true, // 渲染网格背景
      size: 10, // 网格大小 10px
      type: "doubleMesh",
      args: [
        {
          color: "#eee", // 主网格线颜色
          thickness: 1 // 主网格线宽度
        },
        {
          color: "#ddd", // 次网格线颜色
          thickness: 1, // 次网格线宽度
          factor: 4 // 主次网格线间隔
        }
      ]
    },

    // 滚动设置
    scroller: {
      enabled: false, // 启用滚动
      pannable: true // 允许通过拖动来平移视图
    },

    // 是否启用缩略图（小地图）
    minimap: false, // 禁用缩略图

    // 鼠标滚轮设置
    mousewheel: {
      enabled: true, // 启用鼠标滚轮缩放
      modifiers: ["ctrl", "meta"] // 可以通过按下 Ctrl 或 Meta 键来启用缩放
    },

    // 平移设置
    panning: {
      enabled: true, // 启用平移功能
      modifiers: "space" // 需要按住 space 键才能进行拖拽平移 大空格键
    },

    // 交互设置(拖拽移动)
    interacting: {
      nodeMovable: true
    },

    // 拖拽设置
    dragging: {
      enabled: true, // 启用拖拽功能
      ghost: false // 禁用拖拽时的虚影效果
    }
  });

  // 渲染
  graph.fromJSON(originalData.value);
  graph.zoomToFit(); // 缩放
  graph.scale(0.7); // 设置初始缩放比例，例如 0.7 表示缩小到 70%
  graph.centerContent(); // 居中
};

// 左侧模板
const buildStencil = (): void => {
  stencil = new Stencil({
    target: graph, // 指定目标画布
    stencilGraphWidth: 280, // 模板宽度
    // search: { rect: true }, // 搜索框
    collapsable: true, // 可折叠
    groups: [
      {
        name: "basic",
        title: "基础节点",
        // 高度
        graphHeight: 180
      },
      {
        name: "combination",
        title: "组合节点",
        // 布局选项
        layoutOptions: {
          // 每行几列
          columns: 1,
          // 左侧边距
          marginX: 60
        },
        graphHeight: 260
      },
      {
        name: "group",
        title: "节点组",
        graphHeight: 100,
        layoutOptions: {
          columns: 1,
          marginX: 60
        }
      }
    ]
  });
  document.querySelector("#stencil")?.appendChild(stencil.container);
};

// 左侧模板加载数据 stencil.load
const stencilLoadData = () => {
  // 使用统一创建方式
  const createStencilNode = (text: string) =>
    Shape.Rect.create({
      width: 100,
      height: 50,
      attrs: {
        label: { text }
      }
    });

  stencil.load([createStencilNode("业务节点1"), createStencilNode("业务节点2"), createStencilNode("业务节点3")], "basic");
};

// 初始化事件
const initEvent = () => {
  graph.on("cell:click", ({ cell }) => {
    console.log(cell.getAttrs());
    // 将之前被选中的节点样式清除
    curCel?.attr("body/stroke", null);
    // 新的节点赋值
    curCel = cell;
    // 新的节点边框样式设置为红色
    curCel?.attr("body/stroke", "red");

    // 将cell data中Id进行赋值
    formData.id = cell.getData()?.id;

    // console.log("11111", formData);

    if (formData.id) {
      // 模拟请求数据
      setTimeout(() => {
        const tableDataRow = tableData.filter(item => item.id === formData.id)[0];
        formData.title = tableDataRow.title;
        formData.content = tableDataRow.content;
      }, 100);
    } else {
      formData.title = null;
      formData.content = null;
    }
  });
};

// 所有下拉数据
const dropdownData: UnwrapRef<any> = reactive({
  tableData: []
});

const onIdChange = () => {
  // 模拟请求
  setTimeout(() => {
    const tableDataRow = tableData.filter(item => item.id === formData.id)[0];
    formData.title = tableDataRow?.title;
    formData.content = tableDataRow?.content;

    curCel?.setData({
      id: formData.id
    });
    curCel?.attr("label/text", formData.title);
  }, 100);
};

const toJson = () => {
  console.log(graph.toJSON());
};

onMounted(() => {
  init(); // 初始化树数据
  buildStencil();
  stencilLoadData();
  initEvent();
  // 模拟请求数据
  setTimeout(() => {
    dropdownData.tableData = tableData;
  }, 1000);
});
</script>

<style scoped>
#x6Container {
  flex: 1;
  width: 100%;
  height: 100vh;
  position: relative;
}
</style>
